#include "Method.h"
#include "MethodDEClassical.h"

Method * Method::createMethod(Method::SubType subType, Problem * problem, unsigned int popSize, unsigned int iterations)
{
    Method * pMethod = NULL;
    switch (subType)
    {

    case DEClassical:
        pMethod = new MethodDEClassical(subType, problem, popSize, iterations);
        break;
    default:
        pMethod = new MethodDEClassical(subType, problem, popSize, iterations);
    }
    return pMethod;
}

Method::Method(const SubType & subType, Problem * problem, unsigned int popSize, unsigned int iterations):
    mSubType(subType),
    problem(problem),
    populationSize(popSize),
    iterations(iterations)
{
    switch (subType)
    {
    case DEClassical:
        name="DEClassical";
        break;
    default:
        name="DEClassical";
    }
}

Method::~Method() {}

void Method::initializeCost()
{
    cost.resize(getPopulationSize());

    unsigned int i;
    for (i=0; i<getPopulationSize(); i++)
        cost[i]=getProblem()->computeValue(parentPopulation[i]);
}

void Method::initialize()
{
    unsigned int i, j;
    double lower, upper, random;
    RandomLib::Random r;          // Create r
    r.Reseed();

    parentPopulation.resize(getPopulationSize());
    for (i = 0; i <getPopulationSize(); i++)
        parentPopulation[i].resize(getProblem()->getDimention());


    //MATRIX : population size * dimention of objective function
    for(j=0; j<getProblem()->getDimention(); j++)
    {
        lower=getProblem()->getCoordinates()[j].getLowerBound();
        upper=getProblem()->getCoordinates()[j].getUpperBound();
        for (i=0; i<getPopulationSize() ; i++ )
        {
            //generate random number from lower bound to upper
            random=r.Fixed()*(upper-lower)+lower;
            parentPopulation[i][j]=random;
        }
    }
    initializeCost();
}



void Method::printMethod()
{
    std::cout<<getName()<<"  population size: "<<getPopulationSize()<<std::endl;
    getProblem()->printProblem();
}

void Method::printPopulation(const matrix & population)const
{
    unsigned int i,j;
    for(i=0; i<populationSize; i++)
    {
        for(j=0; j<problem->getDimention(); j++)
            std::cout<<population[i][j]<<" ";
        std::cout<<std::endl;
    }
}
void Method::printVector(const std::vector<double> & v)const
{
    unsigned int i;
    for(i=0; i<v.size(); i++)
    {
        std::cout<<v[i]<<" ";
    }
}
